﻿namespace DomainServices.Tools
{
    using Microsoft.Build.Framework;
    using Microsoft.Build.Utilities;
    using DomainServices.Tools.Validation;
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Web.Compilation;
    using System.Web.Hosting;

    public class ValidateDomainServicesTask : Task
    {
        private readonly ILoggingService _loggingService;
        private string _projectDirectory;

        public ValidateDomainServicesTask()
        {
            this._loggingService = new TaskLoggingHelperLoggingService(base.Log);
        }

        public override bool Execute()
        {
            this._projectDirectory = null;
            this.LoggingService.LogMessage(string.Format(CultureInfo.CurrentCulture, "DomainService Validation starting for project {0}", new object[] { Path.GetFileName(this.ProjectPath) }));
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            this.ValidateDomainServices();
            stopwatch.Stop();
            double num = ((double) stopwatch.ElapsedMilliseconds) / 1000.0;
            this.LoggingService.LogMessage(string.Format(CultureInfo.CurrentCulture, "DomainService Validation finished in {0} seconds", new object[] { num }));
            return !this.LoggingService.HasLoggedErrors;
        }

        private string GetFileName(ITaskItem taskItem)
        {
            string itemSpec = taskItem.ItemSpec;
            if (!Path.IsPathRooted(itemSpec))
            {
                itemSpec = Path.GetFullPath(Path.Combine(this.ProjectDirectory, itemSpec));
            }
            return itemSpec;
        }

        private void ValidateDomainServices()
        {
            IEnumerable<string> assemblies = new string[] { this.GetFileName(this.Assembly) }.Concat<string>(from i in this.ReferenceAssemblies select this.GetFileName(i));
            this.WarnIfAssembliesDontExist(assemblies);
            using (ClientBuildManager manager = new ClientBuildManager("/", this.ProjectDirectory))
            {
                if (HostingEnvironment.InitializationException != null)
                {
                    throw new InvalidOperationException(Resource.HttpRuntimeInitializationError, HostingEnvironment.InitializationException);
                }
                using (DomainServiceValidator validator = (DomainServiceValidator) manager.CreateObject(typeof(DomainServiceValidator), false))
                {
                    validator.Validate(assemblies.ToArray<string>(), this.LoggingService);
                }
            }
        }

        private void WarnIfAssembliesDontExist(IEnumerable<string> assemblies)
        {
            foreach (string str in assemblies)
            {
                if (!File.Exists(str))
                {
                    this.LoggingService.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.ClientCodeGen_Input_Assembly_Not_Found, new object[] { str }));
                }
            }
        }

        [Required]
        public ITaskItem Assembly { get; set; }

        private ILoggingService LoggingService
        {
            get
            {
                return this._loggingService;
            }
        }

        private string ProjectDirectory
        {
            get
            {
                if (this._projectDirectory == null)
                {
                    this._projectDirectory = Path.GetDirectoryName(this.ProjectPath);
                }
                return this._projectDirectory;
            }
        }

        [Required]
        public string ProjectPath { get; set; }

        [Required]
        public ITaskItem[] ReferenceAssemblies { get; set; }

        private class TaskLoggingHelperLoggingService : MarshalByRefObject, ILoggingService, DomainServices.Tools.ILogger
        {
            private bool _hasLoggedErrors;
            private TaskLoggingHelper _log;

            public TaskLoggingHelperLoggingService(TaskLoggingHelper log)
            {
                if (log == null)
                {
                    throw new ArgumentNullException("log");
                }
                this._log = log;
            }

            public void LogError(string message)
            {
                this._hasLoggedErrors = true;
                this.Log.LogError(message, new object[0]);
            }

            public void LogError(string message, string subcategory, string errorCode, string helpKeyword, string file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber)
            {
                this._hasLoggedErrors = true;
                this.Log.LogError(subcategory, errorCode, helpKeyword, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, new object[0]);
            }

            public void LogMessage(string message)
            {
                this.Log.LogMessage(message, new object[0]);
            }

            public void LogWarning(string message)
            {
                this.Log.LogWarning(message, new object[0]);
            }

            public void LogWarning(string message, string subcategory, string errorCode, string helpKeyword, string file, int lineNumber, int columnNumber, int endLineNumber, int endColumnNumber)
            {
                this.Log.LogWarning(subcategory, errorCode, helpKeyword, file, lineNumber, columnNumber, endLineNumber, endColumnNumber, message, new object[0]);
            }

            public bool HasLoggedErrors
            {
                get
                {
                    return this._hasLoggedErrors;
                }
            }

            public TaskLoggingHelper Log
            {
                get
                {
                    return this._log;
                }
            }
        }
    }
}

